package com.jpm.jroguefx;


import com.jpm.jroguefx.factories.GraphicsFactory;
import com.jpm.jroguefx.types.MonsterAbility;
import javafx.scene.image.Image;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.BitSet;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Monster implements Cloneable {

    private String id, name, img, summon, group;
    private int lvl, hp, hd, dmg, dex, wis, ac, xp, sumnum;
    private Image image;
    private BitSet abilities = new BitSet(MonsterAbility.values().length);
    private static GraphicsFactory gf = GraphicsFactory.getInstance();
    private static final Logger logger = Logger.getLogger(Monster.class.getName());

    @Override
    public Object clone() throws CloneNotSupportedException {

        return super.clone();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    public int getLvl() {
        return lvl;
    }

    public void setLvl(String lvl) {
        this.lvl = Integer.valueOf(lvl);
    }

    public void setLvl(int lvl) {
        this.lvl = lvl;
    }

    public int getHd() {
        return hd;
    }

    public void setHd(String hd) {
        this.hd = Integer.valueOf(hd);
    }

    public void setHd(int hd) {
        this.hd = hd;
    }

    public int getHp() {
        return hp;
    }

    public void setHp(String hp) {
        this.hp = Integer.valueOf(hp);
    }

    public void setHp(int hp) {
        this.hp = hp;
    }

    public int getDmg() {
        return dmg;
    }

    public void setDmg(String dmg) {
        this.dmg = Integer.valueOf(dmg);
    }

    public void setDmg(int dmg) {
        this.dmg = dmg;
    }

    public int getDex() {
        return dex;
    }

    public void setDex(String dex) {
        this.dex = Integer.valueOf(dex);
    }

    public void setDex(int dex) {
        this.dex = dex;
    }

    public int getWis() {
        return wis;
    }

    public void setWis(String wis) {
        this.wis = Integer.valueOf(wis);
    }

    public void setWis(int wis) {
        this.wis = wis;
    }

    public int getAc() {
        return ac;
    }

    public void setAc(String ac) {
        this.ac = Integer.valueOf(ac);
    }

    public void setAc(int ac) {
        this.ac = ac;
    }

    public int getXp() {
        return xp;
    }

    public void setXp(String xp) {
        this.xp = Integer.valueOf(xp);
    }

    public void setXp(int xp) {
        this.xp = xp;
    }

    public String getSummon() {
        return summon;
    }

    public void setSummon(String summon) {
        this.summon = summon;
    }

    public int getSumnum() {
        return sumnum;
    }

    public void setSumnum(String sumnum) {
        this.sumnum = Integer.valueOf(sumnum);
    }

    public void setSumnum(int sumnum) {
        this.sumnum = sumnum;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Image getImage() {
        return image;
    }

    public String getImg() {
        return img;
    }

    public void setImg(String img) {
        this.img = img;
        this.image = gf.get(img);
    }

    public void setAbility(MonsterAbility ability, boolean bool) {
        if (ability != null) {
            abilities.set(ability.ordinal(), bool);
        }
    }

    public boolean hasAbility(MonsterAbility ability) {
        return abilities.get(ability.ordinal());
    }


    public BitSet getAbilities() {
        return abilities;
    }

    public void setAbilities(BitSet abilities) {
        this.abilities = (BitSet) abilities.clone();
    }


    @Override
    public String toString() {

        StringBuffer sb = new StringBuffer();
        sb.append("<monster>\n");

        for (Method method : getClass().getDeclaredMethods()) {

            if (method.getName().startsWith("get")) {
                String tag = method.getName().substring(3);
                if (method.getReturnType() == String.class || method.getReturnType() == int.class) {
                    try {
                        sb.append("<" + tag + ">" + method.invoke(this) + "</" + tag + ">\n");
                    } catch (IllegalAccessException e) {
                        logger.log(Level.WARNING, "Could not access method for tag " + tag, e);
                    } catch (InvocationTargetException e) {
                        logger.log(Level.WARNING, "Accessing tag " + tag + " threw exception", e);
                    }
                }
            }
        }

        sb.append("<abilities>");

        for (int i = 0; i < abilities.length(); i++) {
            if (abilities.get(i)) {
                sb.append(MonsterAbility.values()[i].name() + " ");
            }
        }

        sb.append("</abilities>\n");
        sb.append("</monster>\n");

        return sb.toString();
    }
}
